﻿(function($) {
    var methods = {
        init: function(options) {
            if ($(this).attr('cascade')) return null;
            return this.each(function() {
                var defaults = {
                    url: location.href,
                    key: 'id',
                    valuedatafield: 'v',
                    textdatafield: 't',
                    type: 'GET',
                    selecteddatafield: null,
                    unselectedoption: { value: '@', text: '-- Please Select --' },
                    beforebinding: null,
                    ondatabinding: null,
                    oncompleted: null
                };
                var opts = jQuery.extend(true, {}, defaults, options);
                $(this).data('cascade', opts);
                var guid = '';
                for (var i = 1; i <= 32; i++) {
                    var n = Math.floor(Math.random() * 16.0).toString(16);
                    guid += n;
                    if ((i == 8) || (i == 12) || (i == 16) || (i == 20))
                        guid += "-";
                }
                $(this).attr('cascade', guid);
                $(this).attr('cascadeindex', 0);

                methods.bind.call($(this), opts);
            });
        },

        bind: function(options) {
            return this.each(function() {
                var cur = $(this);
                var guid = $(this).attr('cascade');
                var defaults = $("select[cascade='" + guid + "'][cascadeindex=0]").data('cascade');
                if (!defaults) return;

                var opts = $.extend(true, {}, defaults, options);

                if (opts.beforebinding && typeof opts.beforebinding === 'function') {
                    opts.beforebinding.call(this);
                }

                cur.unbind('change');
                cur.bind('change', function() { $(this).cascadeselect('bind', opts); });

                var index = $("select[cascade='" + guid + "']").length - 1;
                while (index > parseInt(cur.attr('cascadeindex'))) {
                    $("select[cascade='" + guid + "'][cascadeindex=" + index + "]").each(function() {
                        $(this).remove();
                    });
                    index--;
                }

                var v = cur.val(), completed = true;
                if (v !== opts.unselectedoption.value) {
                    $.ajax({ url: opts.url,
                        dataTytpe: 'json',
                        data: opts.key + '=' + v,
                        async: false,
                        type: opts.type,
                        success: function(data, status) {
                            if (data) {
                                data = eval(data);
                                var defaultbind = true;
                                var select = $("<select cascade='" + guid + "' cascadeindex='" + (parseInt(cur.attr('cascadeindex')) + 1) + "'></select>").appendTo(cur.parent());
                                if (opts.ondatabinding && typeof opts.ondatabinding === 'function') {
                                    data = opts.ondatabinding.call(this, select[0], data);
                                }
                                if (!!data) {
                                    var str = "<option value='" + opts.unselectedoption.value + "'>" + opts.unselectedoption.text + "</option>";
                                    var index = 0, i = 0, len = data.length;
                                    while (i < len) {
                                        str += "<option value='" + data[i][opts.valuedatafield] + "'>" + data[i][opts.textdatafield] + "</option>";
                                        if (data[i][opts.selecteddatafield]) {
                                            index = i + 1;
                                        }
                                        i++;
                                    }

                                    $(str).appendTo(select);
                                    select.get(0).selectedIndex = index;

                                    $(select).bind('change', function() { $(this).cascadeselect('bind', opts); });
                                    if (index > 0) {
                                        $(select).cascadeselect('bind', opts);
                                        completed = false;
                                    }
                                }
                            }
                        }
                    });
                }

                if (completed && opts.oncompleted && typeof opts.oncompleted === 'function') {
                    opts.oncompleted.call(this);
                }
            });
        },

        clear: function(clearself) {
            return this.each(function() {
                var guid = $(this).attr('cascade');
                if (!guid)
                    return;
                $("select[cascade='" + guid + "'][cascadeindex!=0]").each(function() { $(this).remove(); });

                if (!!clearself) {
                    $(this).remove();
                } else {
                    $(this).removeAttr('cascade').removeAttr('cascadeindex').removeData('cascade').unbind('change');
                }
            });
        },

        getvalue: function() {
            var guid = $(this).attr('cascade');
            if (!guid)
                return null;

            var opts = $(this).data('cascade');
            var index = $("select[cascade='" + guid + "']").length - 1;
            var last = $("select[cascade='" + guid + "'][cascadeindex=" + index + "]");
            while ((!last.val() || last.val() === opts.unselectedoption.value) && index > 0) {
                index--;
                last = $("select[cascade='" + guid + "'][cascadeindex=" + index + "]");
            }
            return last.val();
        },

        disable: function() {
            var guid = $(this).attr('cascade');
            if (!guid)
                $(this).attr("disabled", "disabled");
            else {
                var index = $("select[cascade='" + guid + "']").length - 1;
                $("select[cascade='" + guid + "'][cascadeindex=" + index + "]").hide();
                $("select[cascade='" + guid + "']").each(function() { $(this).attr("disabled", "disabled"); });
            }

            return this;
        }
    }

    $.fn.cascadeselect = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.tooltip');
        }
    }
})(jQuery);
